package com.aldobucchi.x.flash.geom
{
	
	
	import flash.geom.Matrix;
	import flash.geom.Point;
	
	
	/**
	 * 
	 * @author aldo.bucchi@gmail.com
	 * 
	 */	
	public class Segment
	{
		
		
		
		private var _pointA:Point;
		
		public function get pointA( ):Point
		{
			return _pointA;
		}
		
		
		
		
		private var _pointB:Point;
		
		public function get pointB( ):Point
		{
			return _pointB;
		}
		
				
				
		
		private var _fromOrigin:Segment;
		
		/**
		 * 
		 * Moves the segment so that pointA becomes 0,0
		 * 
		 * @return 
		 * 
		 */		
		public function get fromOrigin( ):Segment
		{
			
			if ( ! _fromOrigin )
			{
				if ( pointA == PointUtil.ORIGIN ) // avoid creating extra segment
				{
					_fromOrigin = this;
				}
				else
				{
					_fromOrigin = new Segment( PointUtil.ORIGIN, pointB.subtract( pointA ) );
				}
			}
			
			return _fromOrigin;
		}
		


		private var _inverse:Segment;
		
		public function get inverse( ):Segment
		{
			
			if ( ! _inverse )
				_inverse = new Segment( pointB, pointA );
			
			
			return _inverse;		
		}

		
		
		
		private var _angle:Number;
		
		/**
		 * 
		 * Returns the angle of the segment in radians.
		 * Internally, it is calculated by transforming the points to polar coordinates.
		 * 
		 * @return 
		 * 
		 */		
		public function get angle( ):Number
		{
			
			if ( isNaN( _angle ) )
			{
				_angle = PolarPoint.fromPoint( fromOrigin.pointB ).angle;
			}
			
			return _angle;
			
		}
		
		
		

		
		private var _length:Number;
		
		public function get length( ):Number
		{
			if ( isNaN( _length ) )
			{
				_length = Point.distance( pointA, pointB );
			}
			return _length;
		}
		
		
		
		
		
		
		
		
		
		
		
		
		public function Segment( pointA:Point, pointB:Point )
		{
			
			_pointA = pointA;
			
			_pointB = pointB;
						
		}
		
		

		
		public function transform( matrix:Matrix ):Segment
		{
			return new Segment( matrix.transformPoint( pointA ), matrix.transformPoint( pointB ) ); 
		}




		/**
		 * 
		 * Returns a transformation with rotation, translation and scaling.
		 * Scaling is assumed to be regular ( proportional )
		 * 
		 * @param other
		 * @return 
		 * 
		 */
		public function compare( other:Segment ):Transformation2D
		{
		
			var scale:Number = other.length / this.length;

			var rotation:Number = other.angle - this.angle;
			
			var translation:Point = other.pointA.subtract( pointA );	
			
			return new Transformation2D( translation.x, translation.y, scale, scale, rotation );
		}




		
		public function toString( ):String
		{
			return "Segment(" + pointA + " --> " + pointB + ")";
		}
		
		

	}
	
}